package chap_03;

import chap_02.Apple;
import org.junit.jupiter.api.Test;
import org.omg.PortableInterceptor.INACTIVE;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import static java.util.Comparator.comparing;

public class Run {
    @Test
    public void demo_01() {
        Runnable r = () -> System.out.println("Hello World 1");
        r.run();
    }

    @Test
    public void demo_02() {
        final int portNumber = 1337;
        Runnable r = () -> System.out.println(portNumber);
    }

    @Test
    public void demo_03() {
        List<Apple> inventory = Arrays.asList(
                new Apple(80, "green"),
                new Apple(155, "green"),
                new Apple(120, "red")
        );

        // 等价于 inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
        //inventory.sort(Comparator.comparing(Apple::getWeight));
        // 逆序
        //inventory.sort(Comparator.comparing(Apple::getWeight).reversed());
        // 多比对
        inventory.sort(comparing(Apple::getWeight)
                .reversed()
                .thenComparing(Apple::getColor));

        System.out.println(inventory);
    }

    /**
     * 方法引用
     */
    @Test
    public void demo_04() {
        Function<String, Integer> function = Integer::parseInt;
        System.out.println(function.apply("2"));

        // BiPredicate<List<String>, String> contains = (list, element) -> list.contains(element);
        BiFunction<List, Object, Boolean> biFuntion = List::contains;
        Boolean apply = biFuntion.apply(Arrays.asList(1, 3, 2, 4, 5), 3);
        System.out.println(apply);
    }

    /**
     * 构函数引用
     */
    @Test
    public void demo_05() {
        // 空参构造
        Supplier<Apple> c1 = Apple::new;
        Apple apple = c1.get();
        apple.setColor("green");
        System.out.println(apple);

        // 一个参数Integer的构造
        Function<Integer, Apple> c2 = Apple::new;
        Apple apple2 = c2.apply(155);
        System.out.println(apple2);

        // 两个参数的构造
        BiFunction<Integer, String, Apple> c3 = Apple::new;
        Apple red = c3.apply(144, "red");
        System.out.println(red);
    }

    /**
     * 不将构造函数实例化却能够引用它
     */
    @Test
    public void demo_06() {
        Map<String, Function<Integer, Apple>> map = new HashMap<>();
        map.put("apple", Apple::new);

        System.out.println(map.get("apple").apply(150));
    }

    /**
     * 谓词接口
     */
    @Test
    public void demo_07() {
        // negate()方法可以返回一个Prediacate的非
        BiFunction<Integer, String, Apple> c3 = Apple::new;
        Apple redApple = c3.apply(144, "red");
        Predicate<Apple> red = (Apple a) -> "red".equals(a.getColor());
        Predicate<Apple> noRed = red.negate();
        System.out.println(noRed.test(redApple));

        // 把两个Lambda用and方法组合起来，比如一个苹果既是红色又比较重
        Predicate<Apple> redAndHeavyApple =
                red.and(a -> a.getWeight() > 150);

        // 把两个Lambda用or方法组合起来，么是重（150克以上）的红苹果，要么是绿苹果
        Predicate<Apple> redAndHeavyAppleOrGreen =
                red.and(a -> a.getWeight() > 150)
                        .or(a -> "green".equals(a.getColor()));
        System.out.println(redAndHeavyAppleOrGreen.test(redApple));
    }

    /**
     * 函数复合
     */
    @Test
    public void demo_08() {
        //把Function接口所代表的Lambda表达式复合起来
        //Function接口为此配了andThen和compose两个默认方法，它们都会返回Function的一个实例
        //andThen方法会返回一个函数，它先对输入应用一个给定函数，再对输出应用另一个函数
        //andThen 先计算f,在计算g (1+1)*2
        Function<Integer, Integer> f = x -> x + 1;
        Function<Integer, Integer> g = x -> x * 2;
        Function<Integer, Integer> h = f.andThen(g);
        int result = h.apply(1);
        System.out.println(result);

        // compose 先计算g在计算f 1 * 2 + 1
        Function<Integer, Integer> compose = f.compose(g);
        int res = compose.apply(1);
        System.out.println(res);
    }
}
